summaryrefslogtreecommitdiffstats
path: root/src/pages/releases/[version].tsx
blob: 262dac18589d9d4c9169df08e0e737bc1bcb6be6 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
import { Page, PipelineStageError } from "corvos";

import { strapiLoader } from "$/deps/strapi.tsx";
import { releaseStrapiSchema } from "$/schemas/releases.ts";
import { BaseLayout } from "$/ui/base/BaseLayout.tsx";
import { ReleaseCard } from "$/ui/components/ReleaseCard.tsx";
import { SiteHeader } from "$/ui/components/SiteHeader.tsx";
import { CardList } from "$/ui/layouts/CardList.tsx";
import { Container } from "$/ui/layouts/Container.tsx";
import { HList } from "$/ui/layouts/HList.tsx";
import { ActionButton } from "$/ui/objects/ActionButton.tsx";
import { Badge } from "$/ui/objects/Badge.tsx";
import { Body } from "$/ui/objects/Body.tsx";
import { Divider } from "$/ui/objects/Divider.tsx";
import { Heading } from "$/ui/objects/Heading.tsx";
import { Icon } from "$/ui/objects/Icon.tsx";
import site from "@/corvos.config.ts";

export const pages = site.$.pageGenerator(async function* () {
	for await (const item of strapiLoader.loadCollection("corvos-releases", releaseStrapiSchema, {
		"populate[0]": "files",
		"sort[0]": "date:desc",
	})) {
		if (item instanceof PipelineStageError) {
			yield item;
			continue;
		}

		yield new Page(".strapi", item.notes ?? [], {
			...item,
			title: `Corvos ${item.version}`,
			type: "release" as const,
		});
	}
});

export const template = site.$.template({ type: "release" }, (page, pages) => {
	const query = site.$.query(pages);

	const feed = query.type(".rss").match({ type: "releases" }).one();

	const prev = query.type(".html").match({ type: "release" }).prev(page);
	const next = query.type(".html").match({ type: "release" }).next(page);

	return (
		<BaseLayout page={page}>
			<SiteHeader
				mode="compact"
				url={page.url}
				end={
					<div class="l-media__block">
						<ActionButton
							align-block
							class="u-mbs-0"
							href={feed.url}
							icon={<Icon icon="rss-simple" variant="bold" />}
							level="quiet"
							pill
							title="RSS Feed"
						/>
					</div>
				}
			>
				<div class="l-media__block l-media__block--main">
					<Heading class="u-mbs-0 u-elp">{page.data.title}</Heading>
				</div>
			</SiteHeader>

			<Container as="main" class="u-mbs-neutralize h-entry" fixed="150" pad-block pad-inline>
				<HList aria-label="Categories">
					<li>
						<Badge as="strong" pill selected>
							<time class="dt-published" datetime={page.data.date.toISOString()}>
								{page.data.date.toLocaleDateString(undefined, {
									day: "numeric",
									month: "short",
									year: "numeric",
								})}
							</time>
						</Badge>
					</li>
				</HList>

				<Heading as="h1" class="u-mbs-200 p-name" display highlight level="xxl">
					{page.data.title}
				</Heading>

				<Body class="e-content">{{ __html: page.content }}</Body>
			</Container>

			<Divider level="faint" />

			<Container as="footer" class="u-mbs-neutralize" fixed="150" pad-block pad-inline>
				<CardList layout="grid">
					{prev && <ReleaseCard heading-level="h2" page={prev} list />}
					{next && <ReleaseCard heading-level="h2" page={next} list />}
				</CardList>
			</Container>
		</BaseLayout>
	);
});